//This filter is tested and seems to work correctly

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// RobertsCross is an algorithm to apply the roberts cross operator
    /// Edge detection
    /// </summary>
    public class RobertsCross : BaseImageFilter
    {
        //The width and height of the output
        private float m_fOffsetval = 0.0f;
        private double m_dRobscale = 1.0f;

        /// <summary>
        /// default constructor
        /// </summary>
        public RobertsCross()
            : this(1.0f, 0.0f)
        {
        }

        /// <summary>
        /// primary constructor
        /// </summary>
        /// <param name="_dRobscale"></param>
        /// <param name="_fOffsetval"></param>
        public RobertsCross(double _dRobscale, float _fOffsetval)
        {
            m_dRobscale = _dRobscale;
            m_fOffsetval = _fOffsetval;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_robertsCross"></param>
        internal RobertsCross(RobertsCross _robertsCross)
        {
            this.m_dRobscale = _robertsCross.m_dRobscale;
            this.m_fOffsetval = _robertsCross.m_fOffsetval;
        }

        /// <summary>
        /// executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            ApplyRoberts(_bitmap, m_dRobscale, m_fOffsetval);
            return _bitmap;
        }

        /// <summary>
        /// apply_roberts applies a roberts cross operator to an image
        /// roberts cross algorithm..
        /// a) assume the image is grey level (hence RR=GG=BB)
        /// b) use value 0x000000ff to get the BB value
        /// c) apply the operation (e.g. roberts cross).
        /// d) return the result
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        /// <param name="robscale">The robscale.</param>
        /// <param name="offsetval">The offsetval.</param>
        private void ApplyRoberts(UnsafeBitmap _bitmap, double robscale,
                        float offsetval)
        {
            int blue, a, b, c, d;

            UnsafeBitmap bitmap = _bitmap;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            int y = 0;
            int x = 0;

            for (y = 1; y < nHeight - 1; y++)
            {
                for (x = 1; x < nWidth - 1; x++)
                {
                    a = bitmap.GetPixel(x, y).ToArgb() & 0x000000ff;
                    b = bitmap.GetPixel(x + 1, y).ToArgb() & 0x000000ff;
                    c = bitmap.GetPixel(x, y + 1).ToArgb() & 0x000000ff;
                    d = bitmap.GetPixel(x + 1, y + 1).ToArgb() & 0x000000ff;
                    int r1 = a - d;
                    if (r1 < 0) r1 = -r1;
                    int r2 = b - c;
                    if (r2 < 0) r2 = -r2;
                    short gc = (short)(robscale * (r1 + r2));
                    gc = (short)(gc + offsetval);
                    if (gc > 255) gc = 255;
                    bitmap.SetPixel(x, y, Color.FromArgb((int)(0xFF << 24 | gc << 16 | gc << 8 | gc)));
                }
            }
            bitmap.Dispose();
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new RobertsCross(this);
        }
    }
}